package com.crape.common.utils;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;

import magick.CompositeOperator;
import magick.CompressionType;
import magick.DrawInfo;
import magick.ImageInfo;
import magick.MagickException;
import magick.MagickImage;
import magick.PixelPacket;
import magick.PreviewType;

import common.Logger;

/**
 * 图片处理工具类。 核心使用包： ImageMagick-6.3.9-0-Q16-windows-dll.exe 下载地址：http://downloads.jmagick.org/6.3.9/；
 * jmagick-win-6.3.9-Q16.zip 下载地址：http://www.imagemagick.org/ *
 * 
 * @author hjq
 */
public class ImageUtil {
	
	static Logger logger = Logger.getLogger(ImageUtil.class);

    static {
        System.setProperty("jmagick.systemclassloader", "no");
    }

    /**
     * 对图片进行矩形缩放,并保存为jpg格式
     * 
     * @param fromPic 原图片路径
     * @param toPic 新图片路径
     * @param width 新图片宽
     * @param height 新图片高
     * @return
     */
    public static void resetSizeRec(String fromPic, String toPic, int width, int height) throws MagickException {
        ImageInfo info = null;
        MagickImage image = null;
        Dimension imageDim = null;
        MagickImage scaled = null;
        try {
            info = new ImageInfo(fromPic);
            image = new MagickImage(info);
            imageDim = image.getDimension();
            // 图片尺寸的大小处理，如果长宽都小于规定大小，则返回，如果有一个大于规定大小，则等比例缩放
            int srcW = imageDim.width;
            int srcH = imageDim.height;

            // 如果传过来的新图片宽和高参数值为0，那么新图片的宽和高与旧图一样
            if (width == 0 && height == 0) {
                width = srcW;
                height = srcH;
            }

            // 如果传进来的新图宽和高均大于原图的宽和高，那么新图片的宽和高于旧图保持一直
            if (srcH < height && srcW < width) {
                width = srcW;
                height = srcH;
            }

            int tmpH = width;
            int tmpW = height;
            if (srcH == height && srcW == width) {
                // 旧图和新图的宽高一致，不做任何操作
            } else {
                // 在长度和宽度都做了限制，不能超过设定值
                if (srcH > height || srcW > width) {
                    if (srcW > width) {
                        // 如果原图的宽大于新图的宽，那么进行等比压缩
                        tmpH = srcH * width / srcW;
                        srcH = tmpH;
                        srcW = width;
                    }
                    if (srcH > height) {
                        // 如果原图的高大于新图的高，那么进行等比压缩
                        tmpW = srcW * height / srcH;
                        srcW = tmpW;
                        srcH = height;
                    }
                }
            }
            scaled = image.scaleImage(srcW, srcH);// 根据新图的宽和高进行等比压缩.
            scaled.setFileName(toPic);// 保存图片到新的图片路径下
            scaled.writeImage(info);
        } finally {
            if (scaled != null) {
                scaled.destroyImages();
            }
        }
    }

    /**
     * 将图片缩放成一个正方形图片，并保存为jpg格式
     * 
     * @param picFrom 原始图片路径
     * @param picTo 新图片路径
     * @param width 正方形边长
     * @throws MagickException
     */
    public static void resetSizeSquare(String fromPic, String toPic, int width) throws MagickException {
        // 先将图片裁剪成正方形
        ImageUtil.cutToSquare(fromPic, fromPic);
        // 然后进行压缩
        ImageUtil.resetSizeRec(fromPic, toPic, width, width);
    }

    /**
     * 将图片裁剪为正方形，以便压缩
     * 
     * @param fromPic
     * @param toPic
     * @param width
     * @param height
     * @return
     * @throws MagickException
     */
    public static void cutToSquare(String fromPic, String toPic) throws MagickException {
        ImageInfo info = null;
        MagickImage image = null;
        Dimension imageDim = null;
        MagickImage scaled = null;
        try {
            info = new ImageInfo(fromPic);
            image = new MagickImage(info);
            imageDim = image.getDimension();
            // 图片尺寸的大小处理，如果长宽都小于规定大小，则返回，如果有一个大于规定大小，则等比例缩放
            int srcW = imageDim.width;
            int srcH = imageDim.height;

            int w;
            int h;
            int x;
            int y;
            
            if (srcH >= srcW) {
                // 高大于宽
                w = srcW;
                h = srcW;
                x = 0;
                y = (srcH - srcW) / 2;
                ImageUtil.cutImg(fromPic, toPic, w, h, x, y);
            } else if (srcH <= srcW) {
                // 高小于宽
                w = srcH;
                h = srcH;
                x = (srcW - srcH) / 2;
                y = 0;
                ImageUtil.cutImg(fromPic, toPic, w, h, x, y);
            }
        } finally {
            if (scaled != null) {
                scaled.destroyImages();
            }
            if (image != null) {
                image.destroyImages();
            }
        }
    }

    /**
     * <p>
     * 描述：将图片转换为jpg格式
     * </P>
     * 
     * @param imagePath 图片的路径
     * @param newImagePath 新图片的路径
     * @throws MagickException
     */
    public static void converToJpg(String imagePath, String newImagePath) throws MagickException {
        // 创建imageInfo对象
        ImageInfo imageInfo = new ImageInfo(imagePath);
        imageInfo.setMagick("jpg");
        imageInfo.setCompression(CompressionType.JPEGCompression); // 设置压缩

        // 读取imageInfo
        MagickImage image = new MagickImage(imageInfo);

        // 设置新图片的路径
        image.setFileName(newImagePath);
        // 执行
        image.writeImage(imageInfo);
        // 销毁
        image.destroyImages();
    }

    /**
     * 根据后缀名判断文件是否为图片
     * 
     * @param suffix
     * @return
     */
    public static boolean isPicFile(String suffix) {
        if (suffix.equalsIgnoreCase("jpg") || suffix.equalsIgnoreCase("gif") || suffix.equalsIgnoreCase("png")
            || suffix.equalsIgnoreCase("jpeg")) {
            return true;
        } else {
            return false;
        }
    }

    private static final String[] Type = { ".JPG", ".JPEG", ".BMP", ".GIF", ".PNG" };

    public static boolean checkType(String path) {
        for (int i = 0; i < Type.length; i++) {
            if (path.toUpperCase().endsWith(Type[i])) {
                return true;
            } else {
                continue;
            }
        }
        return false;
    }

    /**
     * 创建图片水印
     * 
     * @param filePath 源文件路径 toImg 生成文件位置 logoPath logo路径 pos logo在源图片中的相对位置，以像素点为单位
     * @return
     * @throw MagickException
     */
    public static void createWaterPrintByImg(String filePath, String toImg, String logoPath, Point pos)
                                                                                                       throws MagickException {
        if (!checkType(filePath) || !checkType(toImg) || !checkType(logoPath)) {
            return;
        }

        ImageInfo info = new ImageInfo();
        MagickImage fImage = null;
        MagickImage sImage = null;
        MagickImage fLogo = null;
        MagickImage sLogo = null;
        Dimension imageDim = null;
        Dimension logoDim = null;
        try {
            fImage = new MagickImage(new ImageInfo(filePath));
            imageDim = fImage.getDimension();
            int width = imageDim.width;
            int height = imageDim.height;
            sImage = fImage.scaleImage(width, height);

            fLogo = new MagickImage(new ImageInfo(logoPath));
            // fLogo.transparentImage(PixelPacket.queryColorDatabase("white"),
            // 65535); //设置背景色
            logoDim = fLogo.getDimension();
            int lw = logoDim.width;
            int lh = logoDim.height;

            // 默认或者参数出错时，LOGO放在右下角
            if (width <= (int) pos.getX() || height <= (int) pos.getY()) {
                pos.setLocation(width - lw, height - lh);
            }

            sLogo = fLogo.scaleImage(lw, lh);
            sImage.compositeImage(CompositeOperator.AtopCompositeOp, sLogo, (int) pos.getX(), (int) pos.getY());
            sImage.setFileName(toImg);
            sImage.writeImage(info);
        } finally {
            if (sImage != null) {
                sImage.destroyImages();
            }
        }
    }

    /**
     * 创建文字水印
     * 
     * @param filePath 源文件路径 toImg 生成文件位置 text 水印文本 pos logo在源图片中的相对位置，以像素点为单位 pointSize 用于设置点阵大小
     * @return
     * @throw MagickException
     */
    public static void createWaterPrintByText(String filePath, String toImg, String text, Point pos, int pointSize)
                                                                                                                   throws MagickException {
        if (!checkType(filePath) || !checkType(toImg)) {
            return;
        }

        if (null == text || "".equals(text)) {
            text = "sulliy@sina.com";
        }

        ImageInfo info = new ImageInfo(filePath);
        if (filePath.toUpperCase().endsWith("JPG") || filePath.toUpperCase().endsWith("JPEG")) {
            info.setCompression(CompressionType.JPEGCompression); // 压缩类别为JPEG格式
            info.setPreviewType(PreviewType.JPEGPreview); // 预览格式为JPEG格式
            info.setQuality(95);
        }
        MagickImage aImage = new MagickImage(info);
        Dimension imageDim = aImage.getDimension();
        int width = imageDim.width;
        int height = imageDim.height;

        if (width <= (int) pos.getX() || height <= (int) pos.getY()) {
            pos.setLocation(0, 0);
        }

        int a = 0;
        int b = 0;
        String[] as = text.split("");
        for (String string : as) {
            if (string.matches("[/u4E00-/u9FA5]")) {
                a++;
            }
            if (string.matches("[a-zA-Z0-9]")) {
                b++;
            }
        }
        int tl = a * 12 + b * 6;// 字符长度
        MagickImage scaled = aImage.scaleImage(width, height);
        if (width > tl && height > 5) {
            DrawInfo aInfo = new DrawInfo(info);
            aInfo.setFill(PixelPacket.queryColorDatabase("white"));
            aInfo.setUnderColor(new PixelPacket(65535, 65535, 65535, 65535));// 设置为透明颜色
            aInfo.setPointsize(pointSize);
            // 解决中文乱码问题,自己可以去随意定义个自己喜欢字体，我在这用的微软雅黑
            String fontPath = "C:/WINDOWS/Fonts/MSIMHEI.TTF";
            // String fontPath = "/usr/maindata/MSYH.TTF";
            aInfo.setFont(fontPath);
            aInfo.setTextAntialias(true);
            aInfo.setOpacity(0);// 透明度
            aInfo.setText(text);
            aInfo.setGeometry("+" + ((int) pos.getX() + "+" + (int) pos.getY()));
            scaled.annotateImage(aInfo);
        }
        scaled.setFileName(toImg);
        scaled.writeImage(info);
        scaled.destroyImages();
    }

    /**
     * 切取图片
     * 
     * @param imgPath 原图路径 toPath 生成文件位置 w 图片宽 h 图片高 x x坐标 y y坐标
     * @return
     * @throw MagickException
     */
    public static void cutImg(String imgPath, String toPath, int w, int h, int x, int y) throws MagickException {
        ImageInfo infoS = null;
        MagickImage image = null;
        MagickImage cropped = null;
        Rectangle rect = null;
        try {
            infoS = new ImageInfo(imgPath);
            image = new MagickImage(infoS);
            rect = new Rectangle(x, y, w, h);
            cropped = image.cropImage(rect);
            cropped.setFileName(toPath);
            cropped.writeImage(infoS);
        }catch(Throwable e){
        	logger.error("cat image error", e);
        	throw new MagickException(e.getMessage());
        } finally {
            if (cropped != null) {
                cropped.destroyImages();
            }
        }
    }

    /**
     * 删除图片文件
     * 
     * @param src 图片位置
     * @return
     * @throw
     */
    public static boolean removeFile(String src) throws SecurityException {
        try {
            if (!checkType(src)) {
                return false;
            }

            File file = new File(src);
            return file.delete();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}
